package main

import (
	"bytes"
	"fmt"
	"sync"
)

// main
//
//	@Description: sync.Pool 数据类型用来保存一组可独立访问的临时对象
//
// sync.Pool 本身就是线程安全的，多个 goroutine 可以并发地调用它的方法存取对象；
// sync.Pool 不可在使用之后再复制使用。
func main() {
	//testBytesBuffer()
	testReuseStruct()
	testBigSlice()
}

// --------字节缓冲区复用 (网络编程常用)--------

func testBytesBuffer() {
	//当调用 Pool 的 Get 方法从池中获取元素，没有更多的空闲元素可返回时，就会调用这个 New 方法来创建新的元素。
	//如果你没有设置 New 字段，没有更多的空闲元素可返回时，Get 方法将返回 nil，表明当前没有可用的元素。
	buf := GetBuffer()
	defer PutBuffer(buf)
	buf.WriteString("Hello World")
}

var bufPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	}}

func GetBuffer() *bytes.Buffer {
	buffer := bufPool.Get().(*bytes.Buffer)
	buffer.Reset() // 重要！重置缓冲区
	return buffer
}
func PutBuffer(buf *bytes.Buffer) {
	bufPool.Put(buf)
}

// -------- 结构体重用 (游戏开发场景)----------------

func testReuseStruct() {
	player := NewPlayer()
	fmt.Println(player)
	ReleasePlayer(player)

}

type Player struct {
	ID   int
	Name string
	HP   int
}

var playerPool = sync.Pool{
	New: func() interface{} {
		return &Player{HP: 100} // 初始血量
	},
}

func NewPlayer() *Player {
	p := playerPool.Get().(*Player)
	return p
}
func ReleasePlayer(p *Player) {
	playerPool.Put(p)
}

//-------- 大切片复用 (数据处理场景)--------------

func testBigSlice() {

}

var slicePool = sync.Pool{
	New: func() interface{} {
		return make([]float64, 0, 1024) // 预分配容量
	}}

func GetSlice() []float64 {
	return slicePool.Get().([]float64)[:0] // 重置长度
}
func PutSlice(s []float64) {
	if cap(s) >= 1024 {
		slicePool.Put(s) // 只回收大切片
	}
}
